<template>
  <FormDownloadApplyTable v-if="schema.component === 'ApplyTable'" />
  <UniFormsItem
    v-if="getShow"
    :rules="handleRules()"
    :label="schema.component === 'ApplyTable' ? `上传${schema.label}` : schema.label"
    :name="schema.field"
    :required="getRequired"
    :labelWidth="schema.labelWidth"
    v-bind="getFormItemProps"
  >
    <template v-if="schema.slot">
      <slot :model="formModel" :field="schema.field" />
    </template>
    <template v-else>
      <FormInput v-if="schema.component === 'Input'" />
      <FormInput v-else-if="schema.component === 'InputNumber'" type="number" />
      <FormInputPhone v-else-if="schema.component === 'InputPhone'" />
      <FormInput v-else-if="schema.component === 'InputTextArea'" type="textarea" />
      <FormInput v-else-if="schema.component === 'InputPassword'" type="password" />
      <FormInput v-else-if="schema.component === 'Nickname'" type="nickname" />
      <FormNumberBox v-else-if="schema.component === 'NumberBox'" />
      <FormSelector v-else-if="schema.component === 'Select'" />
      <FormUploadFile v-else-if="schema.component === 'UploadImg'" mediaType="image" />
      <FormUploadFile v-else-if="schema.component === 'UploadFile'" mediaType="doc" />
      <FormUploadFile v-else-if="schema.component === 'UploadVideo'" mediaType="video" />
      <FormDataCheckbox v-else-if="schema.component === 'RadioGroup'" />
      <FormDataCheckbox v-else-if="schema.component === 'CheckboxGroup'" :multiple="true" />
      <FormSwitch v-else-if="schema.component === 'Switch'" />
      <FormTimePicker v-else-if="schema.component === 'TimePicker'" />
      <FormDatePicker v-else-if="schema.component === 'DatePicker'" />
      <FormDatePicker v-else-if="schema.component === 'DateTimePicker'" type="datetime" />
      <FormYearMonthPicker v-else-if="schema.component === 'YearPicker'" />
      <FormYearMonthPicker v-else-if="schema.component === 'MonthPicker'" fields="month" />
      <FormAreaPicker v-else-if="schema.component === 'AreaPicker'" />
      <FormAreaStreetPicker v-else-if="schema.component === 'AreaStreetPicker'" />
      <FormSelectAddress v-else-if="schema.component === 'ChooseLocation'" />
      <FormHonor v-else-if="schema.component === 'Honor'" />
      <FormInputSearch v-else-if="schema.component === 'InputSearch'" />
      <FormTianyanchaScore v-else-if="schema.component === 'TianyanchaScore'" />
      <FormPolicyService v-else-if="schema.component === 'PolicyService'" />
      <FormUploadFile v-else-if="schema.component === 'ApplyTable'" mediaType="doc" />
      <FormSelectIndustry v-else-if="schema.component === 'SelectIndustry'" />
      <!-- 附件组件 -->
      <FormUploadFile v-else-if="schema.component === 'Attachment'" mediaType="doc" :limit="1" />
    </template>
  </UniFormsItem>
</template>

<script setup lang="ts">
  import UniFormsItem from '../uni_modules/uni-forms-item/uni-forms-item.vue';
  import { computed, type PropType, provide, toRaw, unref } from 'vue';
  import { type FormProps, type FormSchema } from '../types/form';
  import { isBoolean, isFunction } from '@/utils/is';
  import FormInput from './FormInput.vue';
  import FormSelector from './FormSelector.vue';
  import FormUploadFile from './upload/FormUploadFile.vue';
  import { type Rules } from '../types/validator';
  import { cloneDeep } from 'lodash-es';
  import { comLabelPositionTop, createPlaceholderMessage } from '../helper';
  import FormDataCheckbox from './FormDataCheckbox.vue';
  import FormNumberBox from './FormNumberBox.vue';
  import FormSwitch from './FormSwitch.vue';
  import FormTimePicker from './FormTimePicker.vue';
  import FormDatePicker from './FormDatePicker.vue';
  import FormYearMonthPicker from './FormYearMonthPicker.vue';
  import FormSelectAddress from './FormSelectAddress.vue';
  import FormAreaPicker from './FormAreaPicker.vue';
  import { phoneReg, telReg } from '@/utils/Reg';
  import FormHonor from './FormHonor.vue';
  import FormInputSearch from './FormInputSearch.vue';
  import FormTianyanchaScore from './FormTianyanchaScore.vue';
  import FormPolicyService from './FormPolicyService.vue';
  import { type OnchangeArgument } from '../types';
  import FormDownloadApplyTable from './FormDownloadApplyTable.vue';
  import FormAreaStreetPicker from './FormAreaStreetPicker.vue';
  import FormInputPhone from './FormInputPhone.vue';
  import FormSelectIndustry from './FormSelectIndustry.vue';

  const props = defineProps({
    schema: {
      type: Object as PropType<FormSchema>,
      default: () => ({}),
    },
    formProps: {
      type: Object as PropType<FormProps>,
      default: () => ({}),
    },
    allDefaultValues: {
      type: Object as PropType<Recordable>,
      default: () => ({}),
    },
    formModel: {
      type: Object as PropType<Recordable>,
      default: () => ({}),
    },
    setFormModel: {
      type: Function as PropType<(key: string, value: any) => void>,
      default: null,
    },
    onSchemaChange: {
      type: Function as PropType<(op: OnchangeArgument) => void>,
      default: null,
    },
  });

  const getFormItemProps = computed(() => {
    const { schema } = props;
    const itemProps = schema?.itemProps || {};
    if (comLabelPositionTop.includes(schema.component)) {
      itemProps.labelPosition = 'top';
    }
    return itemProps;
  });

  const getComponentsProps = computed(() => {
    const { schema } = props;
    let { componentProps = {} } = schema;
    if (isFunction(componentProps)) {
      componentProps = componentProps({ schema }) ?? {};
    }
    return componentProps as Recordable;
  });

  const getValues = computed(() => {
    const { allDefaultValues, formModel, schema } = props;
    const { mergeDynamicData } = props.formProps;
    return {
      field: schema.field,
      model: formModel,
      values: {
        ...mergeDynamicData,
        ...allDefaultValues,
        ...formModel,
      } as Recordable,
      schema: schema,
    };
  });

  const getDisable = computed(() => {
    const { disabled: globDisabled } = props.formProps;
    const { dynamicDisabled } = props.schema;
    const { disabled: itemDisabled = false } = unref(getComponentsProps);
    let disabled = !!globDisabled || itemDisabled;
    if (isBoolean(dynamicDisabled)) {
      disabled = dynamicDisabled;
    }
    if (isFunction(dynamicDisabled)) {
      disabled = dynamicDisabled(unref(getValues));
    }
    return disabled;
  });

  const getShow = computed(() => {
    const { ifShow } = props.schema;
    let isIfShow = true;
    if (isBoolean(ifShow)) {
      isIfShow = ifShow;
    } else if (isFunction(ifShow)) {
      isIfShow = ifShow({
        ...unref(getValues),
        setFormModel: ({ field, value }) => {
          props?.setFormModel(field, value);
        },
      });
    }
    return isIfShow;
  });

  const getRequired = computed(() => {
    const { required } = props.schema;
    return isFunction(required) ? required(unref(getValues)) : required;
  });

  const handleRules = () => {
    const {
      label,
      required,
      rules: defRules = [],
      component,
      rulesMessageJoinLabel,
    } = props.schema;

    const { rulesMessageJoinLabel: globalRulesMessageJoinLabel } = props.formProps;
    const joinLabel = Reflect.has(props.schema, 'rulesMessageJoinLabel')
      ? rulesMessageJoinLabel
      : globalRulesMessageJoinLabel;

    let rules: Rules[] = cloneDeep(defRules) as Rules[];

    const defaultMsg = createPlaceholderMessage(component) + `${joinLabel ? label : ''}`;

    // const getRequired = isFunction(required) ? required(unref(getValues)) : required;
    /*
     * 1、若设置了required属性，又没有其他的rules，就创建一个验证规则；
     * 2、若设置了required属性，又存在其他的rules，则只rules中不存在required属性时，才添加验证required的规则
     *     也就是说rules中的required，优先级大于required
     */
    if (getRequired.value) {
      const requiredIndex: number = rules.findIndex((rule) => Reflect.has(rule, 'required'));
      if (requiredIndex === -1) {
        rules.push({ required: getRequired.value, errorMessage: defaultMsg });
      }
    }

    if (component === 'InputPhone') {
      rules.push({
        validateFunction: (rule, value, data, callback) => {
          if (phoneReg.test(value) || telReg.test(value)) {
            return true;
          } else {
            callback(`请输入正确的${label}`);
          }
          return false;
        },
      });
    }
    return rules;
  };

  provide('FormItem', {
    getValues,
    getDisable,
    getComponentsProps,
    formProps: props.formProps,
    setFormModel: (value: any, isSetVal: boolean = true) => {
      const { field, component, isOnChange, isInternalInterface, dataType } = props.schema;
      if (isSetVal) props?.setFormModel(field, value);
      if (isOnChange) {
        props?.onSchemaChange({
          field,
          component,
          val: toRaw(value),
          isInternalInterface,
          dataType,
        });
      }
    },
  });
</script>

<style scoped></style>
